#include <QtGui>
#include "RequestDescriptor.h"
#include "DataModel.h"
#include "DlgDataEdit.h"
#include "ModTimeline.h"
#include "WidTimeline.h"
#include "scImpl.h"

#define FCT "WidTimeline::WidTimeline"
WidTimeline::WidTimeline(QWidget * parent) :
	WidSybilView(parent), state(WTL_INIT), entity(PK_UNDEF), ik(PK_UNDEF), blockSig(false)
{
	ui.setupUi(this);
	ui.identities->clear();
	ui.iks->clear();
	connect(ui.identities, SIGNAL(currentIndexChanged(int)), this, SLOT(identitiesChangedSl(int)));
	connect(ui.iks, SIGNAL(currentIndexChanged(int)), this, SLOT(iksChangedSl(int)));
	connect(ui.butNew, SIGNAL(clicked()), this, SLOT(newDatasetSl()));
	ui.table->horizontalHeader()->setVisible(true);
	ui.table->verticalHeader()->setVisible(true);
	ui.table->verticalHeader()->setDefaultSectionSize(ui.table->fontMetrics().height()+4);
	connect(ui.table, SIGNAL(pressed(const QModelIndex &)), this, SLOT(mouseTableSl(const QModelIndex &)));
	// There is no button information for a double click signal!
	connect(ui.table, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(correctSl()));
	// no need to set the model since we don't know yet for which table
	setEnabled(false); // we have to wait for the metadata to arrive
	RequestDescriptor *rd(new RequestDescriptor(Request(EID_M_ENTITIES)));
	transId=DataModel::get()->requestData(rd);
	state=WTL_ENTITIES;
	setInfoText();
	if(!transId)
		dataChangedSl(0);
}

#undef FCT
#define FCT "WidTimeline::~WidTimeline"
WidTimeline::~WidTimeline()
{
}

#undef FCT
#define FCT "WidTimeline::dataChangedSl"
void WidTimeline::dataChangedSl(unsigned long transactionId)
{
	if(transactionId && transactionId!=transId)
	{
		ctrc(Trc::LOOP,APP,FCT)<<"skipped trans "<<transactionId<<" waiting for "<<transId<<endl;
		return;
	}
	if(transactionId)
		transId=0;
	DataModel * dm(DataModel::get());
	if(state==WTL_ENTITIES)
	{ // we are still in the setup phase
		blockSig=true;
		ui.identities->clear();
		ui.identities->addItem(tr("-select-"), QVariant(PK_UNDEF));
		DataObjects & obs(dm->getTable(EID_M_ENTITIES).getPayload().dos);
		ctrc(Trc::WORK,APP,FCT)<<"creating "<<obs.size()<<" entries"<<endl;
		for(DataObjects::const_iterator it(obs.begin()); it!=obs.end(); ++it)
			if((DataDomain)it->getPayload().at(M_ENTITIES_DOMAIN).getAsInt()==DOMAIN_DATATL)
			{
				ctrc(Trc::LOOP,APP,FCT)<<"adding entity "<<it->getPayload().at(M_ENTITIES_NAME)<< "("<<it->getPk()<<")"<<endl;
				ui.identities->addItem(it->getPayload().at(M_ENTITIES_NAME).getQString(), QVariant((uint)it->getPk()));
			}
		ui.identities->setCurrentIndex(0);
		state=WTL_IKS;
		setEnabled(true);
		ui.butNew->setEnabled(false);
		ui.iks->setEnabled(false);
		setInfoText();
		blockSig=false;
	}
	else if(state==WTL_IKS)
	{
		blockSig=true;
		ui.iks->clear();
		ui.iks->addItem(tr("-select-"), QVariant(PK_UNDEF));
		DataTable_ & dt(dm->getTable(entity).getPayload());
		DataObjects & obs(dt.dos);
		ctrc(Trc::WORK,APP,FCT)<<"creating "<<obs.size()<<" iks"<<endl;
		PkType oldIk(PK_UNDEF);
		for(DataObjects::const_iterator it(obs.begin()); it!=obs.end(); ++it)
		{
			if(it->getIk()!=oldIk)
			{
				oldIk=it->getIk();
				ctrc(Trc::LOOP,APP,FCT)<<"adding ik "<<oldIk<< "("<<it->getPk()<<")"<<endl;
				ui.iks->addItem(it->getPayload().at(dt.niceNameCol).getAsQString(true), QVariant((uint)oldIk));
			}
		}
		ui.iks->setCurrentIndex(0);
		state=WTL_DATA;
		ui.butNew->setEnabled(true);
		ui.iks->setEnabled(true);
		setInfoText();
		blockSig=false;
	}
	else
		ctrc(Trc::LOOP,APP,FCT)<<"updating through table model for "<<entity<<endl;
}

#undef FCT
#define FCT "WidTimeline::dataMarkSl"
void WidTimeline::dataMarkSl()
{
	ModTable * mt(static_cast<ModTable *>(ui.table->model()));
	if(mt)
		mt->setTouched();
}

#undef FCT
#define FCT "WidTimeline::mouseTableSl"
void WidTimeline::mouseTableSl(const QModelIndex & index)
{
	ctrc(Trc::WORK,APP,FCT)<<"mbut "<<QApplication::mouseButtons()<<endl;
	if(QApplication::mouseButtons()!=Qt::RightButton)
		return;
	QMenu cmenu(this);
	cmenu.addAction(tr("edit data"), this, SLOT(correctSl()));
	cmenu.addSeparator();
	cmenu.addAction(tr("new entry"), this, SLOT(newDatasetSl()));
	cmenu.exec(ui.table->mapToGlobal(ui.table->visualRect(index).center()));
}

#undef FCT
#define FCT "WidTimeline::setInfoText"
void WidTimeline::setInfoText()
{
	if(state==WTL_ENTITIES)
		ui.info->setText(tr("getting e-data"));
	else if(state==WTL_IKS)
		ui.info->setText(tr("getting i-data"));
	else
	{
		if(entity==PK_UNDEF)
			ui.info->setText(tr("- "));
		else
		{
			DataModel *dm(DataModel::get());
			const ColDescs & attrs(dm->getTable(entity).getPayload().attrs);
			QString related(tr("related: "));
			bool first(true);
			for(ColDescs::const_iterator it(attrs.begin()); it!=attrs.end(); ++it)
			{
				if(it->funct==AFUNCT_FIK || it->funct==AFUNCT_FPK)
				{
					if(first)
						first=false;
					else
						related+=", ";
					related+=dm->getTable(it->target).getNameQ();
				}
			}
			if(first)
				related+=tr("none");
			related+=" ";
			ui.info->setText(related);
		}
	}
}

#undef FCT
#define FCT "WidTimeline::newDatasetSl"
void WidTimeline::newDatasetSl()
{
	// TODO feature - create new identity
	// ctrc(Trc::WORK,APP,FCT)<<"entity"<<entity<<endl;
	DlgDataEdit dlg(entity, PK_UNDEF, this);
	if(dlg.exec()==QDialog::Rejected)
	{
		ctrc(Trc::WORK,APP,FCT)<<"dialog canceled"<<endl;
		return;
	}
	// accept slot of dialog saves (and commits!) data
}

#undef FCT
#define FCT "WidTimeline::correctSl"
void WidTimeline::correctSl()
{
	// ctrc(Trc::WORK,APP,FCT)<<"entity"<<entity<<endl;
	QModelIndex idx(ui.table->selectionModel()->currentIndex());
	if(!idx.isValid())
	{
		ctrc(Trc::WORK,APP,FCT)<<"invalid index"<<endl;
		return;
	}
	DlgDataEdit dlg(entity, static_cast<ModTable *>(ui.table->model())->mapRow2Pk(idx.row()), this);
	if(dlg.exec()==QDialog::Rejected)
	{
		ctrc(Trc::WORK,APP,FCT)<<"dialog canceled"<<endl;
		return;
	}
	// accept slot of dialog saves (and commits!) data
}

#undef FCT
#define FCT "WidTimeline::identitiesChangedSl"
void WidTimeline::identitiesChangedSl(int index)
{
	if(blockSig)
		return;
	entity=ui.identities->itemData(index).toUInt();
	ctrc(Trc::WORK,APP,FCT)<<"switching to "<<entity<<endl;
	if(entity!=PK_UNDEF)
	{
		blockSig=true;
		int idx(ui.identities->findData(QVariant(PK_UNDEF)));
		if(idx>=0)
		{
			ui.identities->removeItem(idx);
		}
		state=WTL_IKS;
		ui.butNew->setEnabled(false);
		ui.iks->clear();
		ui.iks->setEnabled(false);
		ModTimeline *oldMod(dynamic_cast<ModTimeline*>(ui.table->model()));
		ui.table->setModel(0);
		delete oldMod; // doesn't hurt if zero
		setInfoText();
		blockSig=false;
		// Probably we should include also IKs which do not exist in the
		// current timeslice - for simplicity we leave it out for now.
		RequestDescriptor *rd(new RequestDescriptor(Request(entity, DataModel::get()->getDeadlineUTC())));
		transId=DataModel::get()->requestData(rd);
		if(!transId)
			dataChangedSl(0);
	}
	else
		setInfoText();
}

#undef FCT
#define FCT "WidTimeline::iksChangedSl"
void WidTimeline::iksChangedSl(int index)
{
	if(blockSig)
		return;
	ik=ui.iks->itemData(index).toUInt();
	ctrc(Trc::WORK,APP,FCT)<<"switching to IK "<<entity<<endl;
	if(ik!=PK_UNDEF)
	{
		int idx(ui.iks->findData(QVariant(PK_UNDEF)));
		if(idx>=0)
		{
			blockSig=true;
			ui.iks->removeItem(idx);
			blockSig=false;
		}
		ModTimeline *oldMod(dynamic_cast<ModTimeline*>(ui.table->model()));
		ui.table->setModel(new ModTimeline(entity, ik, this));
		delete oldMod; // doesn't hurt if zero
	}
	setInfoText();
}
